/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package haw.pr2.A2a.implementations;
import haw.pr2.A2a.interfaces.*;
import static haw.pr2.A2a.implementations.UtilityclassValues.*;
/**
 *
 * @author Fabian Heidorn, Alexander Kaack
 */
class SpeedInMpS extends AbstractScalar<Speed> implements Speed, Comparable<Speed> {
    
    private final double speedInMps;
    
    SpeedInMpS(double speedInMps) {
        this.speedInMps=speedInMps;
    }

    @Override
    public Speed inverse() {
        return new SpeedInMpS(-this.speedInMps);
    }

    @Override
    public Speed add(Speed value) {
        return new SpeedInMpS(this.speedInMps+value.mpS());
    }

    @Override
    public Speed sub(Speed value) {
        return new SpeedInMpS(this.speedInMps-value.mpS());
    }

    @Override
    public Speed mul(double value) {
        return new SpeedInMpS(this.speedInMps*value);
    }

    @Override
    public Speed div(double value) {
        return new SpeedInMpS(this.speedInMps/value);
    }

    @Override
    public double div(Speed value) {
        return this.mpS()/value.mpS();
    }

    @Override
    public boolean isZero() {
        return this.equals(ZERO_SPEED);
    }

    @Override
    public boolean isValid() {
        return true;
    }

    @Override
    public double mpS() {
        return this.speedInMps;
    }

    @Override
    public double kmH() {
        return this.mpS()*UtilityclassValues.MPS_IN_KMH;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof Speed)) return false;
        return this.compareTo((Speed)obj) == 0;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 53 * hash + (int) (Double.doubleToLongBits(this.speedInMps) ^ (Double.doubleToLongBits(this.speedInMps) >>> 32));
        return hash;
    }
    
    @Override
    public int compareTo(Speed s) {
        return Double.compare(this.mpS() , s.mpS());
    }
    
    // @Override
    public static Speed valueOf(double value) {
        return new SpeedInMpS(value);
    }
    
    @Override
    public Force dragForce(Speed maxSpeed, Power maxPower) {
            final double dragConst = Math.abs(maxPower.w() / (Math.pow(maxSpeed.mpS(), 3)));
            return forceInN(dragConst  * (Math.pow(this.mpS(), 2) * Math.signum(this.inverse().mpS())));
    }
    @Override
    public double toDouble() {
        return this.mpS();
    }

    @Override
    public Length mulT(TimeDiff td) {
        return new LengthInM(this.mul(td.s()).mpS());
    }
}